package com.zhihuishu.micro.course.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.zhihuishu.micro.course.dao.MeetCourseMapper;
import com.zhihuishu.micro.course.helper.RedisKeyHelper;
import com.zhihuishu.micro.course.model.MeetCourse;
import com.zhihuishu.micro.course.model.ScoreAssessRule;
import com.zhihuishu.micro.course.service.MeetCourseService;
import com.zhihuishu.micro.course.service.ScoreAssessRuleService;
import com.zhihuishu.toolkit.helper.BeanHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper.Handler;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

@Service("meetCourseService")
public class MeetCourseServiceImpl extends BaseService implements MeetCourseService {
    protected Logger logger = LoggerFactory.getLogger(getClass());
	@Resource
	private MeetCourseMapper meetCourseMapper;

	@Resource
	private ScoreAssessRuleService scoreAssessRuleService;

	// 缓存有效期
	private final int DEFAULT_EXPIRE = 7200;

	/**
	 * 数据库中获取meetCourse集合对象
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午2:00:03
	 * @param courseId
	 * @return
	 */
	public List<MeetCourse> loadMeetCourseList(Long courseId) {
		return meetCourseMapper.getMeetCourseList(courseId);
	}

	@Override
	public List<MeetCourse> getMeetCourseList(Long courseId) {
		Assert.notNull(courseId, "courseId must not be null");

		List<MeetCourse> list = this.getRedisMeetCourseListData(courseId);

		if (CollectionUtils.isEmpty(list)) {
			return this.setRedisMeetCourseList(courseId);
		}

		return list;
	}

	/**
	 * 数据库中获取meetCourse对象
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午12:19:36
	 * @param meetCourseId
	 * @return
	 */
	public MeetCourse loadMeetCourse(Long meetCourseId) {
		return meetCourseMapper.getMeetCourse(meetCourseId);
	}

	@Override
	public MeetCourse getMeetCourse(Long meetCourseId) {
		Assert.notNull(meetCourseId, "meetCourseId must not be null");

		MeetCourse meetCourse = this.getRedisMeetCourseData(meetCourseId);

		if (null == meetCourse) {
			meetCourse = this.loadMeetCourse(meetCourseId);
			return this.setRedisMeetCourseData(meetCourse);
		}

		return meetCourse;
	}

	@Override
	public int findMeetCourseCount(Long courseId) {
		return meetCourseMapper.findMeetCourseCount(courseId);
	}

	@Transactional
	public MeetCourse save(MeetCourse meetCourse) {
		Assert.notNull(meetCourse, "meetCourse must not be null");
		Assert.notNull(meetCourse.getCourseId(), "meetCourse.getCourseId() must not be null");

		meetCourseMapper.save(meetCourse);
		if(meetCourse.getMeetCourseId() == null){
			logger.error("见面课保存后返回id为null,课程id为：", meetCourse.getCourseId());
		}
		// 存缓存
		meetCourse = this.setRedisMeetCourseData(meetCourse);

		// 刷新setkey
		this.setRedisMeetCourseIds(meetCourse.getCourseId(), meetCourse.getMeetCourseId());

		return meetCourse;
	}

	@Transactional
	public void remove(Long meetCourseId) {
		Assert.notNull(meetCourseId, "meetCourseId must not be null");

		MeetCourse meetCourse = this.loadMeetCourse(meetCourseId);

		// 获取考核规则 减少见面课分数占比和总分
		ScoreAssessRule scoreAssessRule = scoreAssessRuleService.findByCourseId(meetCourse.getCourseId());
		if (null != scoreAssessRule && !StringUtils.isEmpty(scoreAssessRule.getMeetCourseScoreShare())) {
			Double meetCourseScoreShare = (StringUtils.isEmpty(meetCourse.getCheckScore()) ? new Double(0)
					: meetCourse.getCheckScore())
					+ (StringUtils.isEmpty(meetCourse.getSiteScore()) ? new Double(0) : meetCourse.getSiteScore());
			scoreAssessRule.setMeetCourseScoreShare(scoreAssessRule.getMeetCourseScoreShare() - meetCourseScoreShare);
			scoreAssessRule.setTotalScore(scoreAssessRule.getTotalScore() - meetCourseScoreShare);
			scoreAssessRuleService.update(scoreAssessRule);
		}

		meetCourseMapper.remove(meetCourseId);

		// 删除缓存
		this.removeCache(meetCourseId);

	}

	@Transactional
	public void update(MeetCourse meetCourse) {
		Assert.notNull(meetCourse, "meetCourse must not be null");
		Assert.notNull(meetCourse.getMeetCourseId(), "meetCourse.getMeetCourseId() must not be null");

		meetCourseMapper.update(meetCourse);

		// 删除缓存然后新增
		this.removeCache(meetCourse.getMeetCourseId());
		meetCourse = this.loadMeetCourse(meetCourse.getMeetCourseId());
		this.setRedisMeetCourseData(meetCourse);
	}

	/**
	 * 获取redis中的数据 (MeetCourseListData)
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午5:46:05
	 * @param courseId
	 * @return
	 */
	public List<MeetCourse> getRedisMeetCourseListData(final long courseId) {

		final List<MeetCourse> meetList = new ArrayList<MeetCourse>();

		// 从缓存中获取数据
		jedisExecutor.execute( new Handler() {
			@Override
			public void handle(Jedis jedis) {

				String key = RedisKeyHelper.getMeetCourseIdKey(courseId);
				if (jedis.exists(key)) {

					Set<String> set = jedis.zrange(key, 0, -1);
					

					// 如果Key存在
					if (!CollectionUtils.isEmpty(set)) {
						
						Pipeline p = jedis.pipelined();

						// 使用管道，从Redis中查询信息
						for (String meetCourseId : set) {
							p.hgetAll(RedisKeyHelper.getMeetCourseKey(Long.valueOf(meetCourseId)));
						}

						List<Object> list = p.syncAndReturnAll();

						if (!CollectionUtils.isEmpty(list)) {
							for (Object obj : list) {

								if (obj == null) {
									continue;
								}

								@SuppressWarnings("unchecked")
								Map<String, String> hash = (Map<String, String>) obj;
								if (CollectionUtils.isEmpty(hash) || hash.get("meetCourseId") == null) {
									continue;
								}
								MeetCourse meetCourse = BeanHelper.transTo(hash, MeetCourse.class);
								//标识见面课完整度是否完整
								setMeetCourseComplete(meetCourse);
								meetList.add(meetCourse);

							}
						}
					}
				}
			}
		});

		return meetList;
	}

	/**
	 * 存值(MeetCourseList)对象到redis
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午5:20:57
	 * @param courseId
	 * @return
	 */
	public List<MeetCourse> setRedisMeetCourseList(final long courseId) {
		List<MeetCourse> list = this.loadMeetCourseList(courseId);

		if (CollectionUtils.isEmpty(list)) {
			return null;
		}

		// 存value到缓存
		for (MeetCourse meetCourse : list) {

			final MeetCourse meetcourse = meetCourse;
			jedisExecutor.execute( new Handler() {
				@Override
				public void handle(Jedis jedis) {
					jedis.zadd(RedisKeyHelper.getMeetCourseIdKey(courseId), meetcourse.getMeetCourseId(),meetcourse.getMeetCourseId().toString());// 将课程id存到set集合中
					jedis.hmset(RedisKeyHelper.getMeetCourseKey(meetcourse.getMeetCourseId()),
							BeanHelper.describe(meetcourse)); // 存对象
					jedis.expire(RedisKeyHelper.getMeetCourseIdKey(courseId), DEFAULT_EXPIRE);
				}
			});

			setMeetCourseComplete(meetCourse);
		}

		return list;
	}

	/**
	 * 存keys
	 * 
	 * @author Rain
	 * @time 2016年12月19日-下午2:02:58
	 * @param courseId
	 *            课程id
	 * @param meetCourseId
	 *            见面课id
	 */
	public void setRedisMeetCourseIds(final Long courseId, final Long meetCourseId) {
		// 存key到缓存
		jedisExecutor.execute( new Handler() {
			@Override
			public void handle(Jedis jedis) {
				jedis.zadd(RedisKeyHelper.getMeetCourseIdKey(courseId), meetCourseId, meetCourseId.toString());
				jedis.hmset(RedisKeyHelper.getMeetCourseKey(meetCourseId),BeanHelper.describe(loadMeetCourse(meetCourseId))); // 存对象
				jedis.expire(RedisKeyHelper.getMeetCourseIdKey(courseId), DEFAULT_EXPIRE);
			}
		});
	}

	/**
	 * 存值(MeetCourse)对象到redis
	 * 
	 * @author Rain
	 * @time 2016年9月13日-上午11:06:10
	 * @param courseId
	 * @return
	 */
	public MeetCourse setRedisMeetCourseData(final MeetCourse meetCourse) {

		if (meetCourse == null || meetCourse.getMeetCourseId() == null ) {
			return null;
		}

		final Map<String, String> map = BeanHelper.describe(meetCourse);
		if (!CollectionUtils.isEmpty(map)) {
			jedisExecutor.execute( new Handler() {
				@Override
				public void handle(Jedis jedis) {
					jedis.hmset(RedisKeyHelper.getMeetCourseKey(meetCourse.getMeetCourseId()), map);
					jedis.expire(RedisKeyHelper.getMeetCourseKey(meetCourse.getMeetCourseId()), DEFAULT_EXPIRE);
				}
			});
		}

		return meetCourse;
	}

	/**
	 * 获取redis中的数据 (MeetCourse)
	 * 
	 * @author Rain
	 * @time 2016年9月13日-上午11:51:42
	 * @param meetCourseId
	 * @return
	 */
	public MeetCourse getRedisMeetCourseData(final long meetCourseId) {
		final MeetCourse meetCourse = new MeetCourse();
		jedisExecutor.execute( new Handler() {
			@Override
			public void handle(Jedis jedis) {
				MeetCourse dto = null;
				String key = RedisKeyHelper.getMeetCourseKey(meetCourseId);
				if (jedis.exists(key)) {
					// 如果Key存在，将信息转换为课程DTO
					Map<String, String> map = jedis.hgetAll(key);
					if (!CollectionUtils.isEmpty(map) && map.get("meetCourseId") != null) {
						dto = BeanHelper.transTo(map, MeetCourse.class);
					}
				}
				if (dto != null && dto.getMeetCourseId() != null) {
					BeanHelper.copyProperties(dto, meetCourse);
				}
			}
		});
		return meetCourse.getMeetCourseId() != null ? meetCourse : null;
	}

	/**
	 * 清楚见面课缓存
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午12:15:22
	 * @param courseId
	 */
	public void removeCache(final long meetCourseId) {
		jedisExecutor.execute( new Handler() {
			@Override
			public void handle(Jedis jedis) {
				jedis.del(RedisKeyHelper.getMeetCourseKey(meetCourseId));
			}
		});
	}

	/**
	 * 清楚见面课keys
	 * 
	 * @author Rain
	 * @time 2016年9月13日-下午12:15:22
	 * @param courseId
	 */
	@SuppressWarnings("unused")
	private void removeCacheKeys(final long courseId) {
		jedisExecutor.execute( new Handler() {
			@Override
			public void handle(Jedis jedis) {
				jedis.del(RedisKeyHelper.getMeetCourseIdKey(courseId));
			}
		});
	}

	/**
	 * 设置见面完整标识
	 * 
	 * @author yulijin
	 * @date 2016年10月13日 下午4:50:58
	 * @param meetCourse
	 */
	private void setMeetCourseComplete(MeetCourse meetCourse) {
		boolean flag = true;
		if (StringUtils.isEmpty(meetCourse.getCourseTopic())) {
			flag = false;
		}
		if (StringUtils.isEmpty(meetCourse.getTaskType())) {
			flag = false;
		}
		if (StringUtils.isEmpty(meetCourse.getSpeakerName())) {
			flag = false;
		}
		if (StringUtils.isEmpty(meetCourse.getTeachRequire())) {
			flag = false;
		}
		meetCourse.setComplete(flag);
	}

	@Override
	public List<Map<String, Object>> getMeetCourseUpdateTimeByCourseIds(List<Long> courseIds) {
		return meetCourseMapper.getMeetCourseUpdateTimeByCourseIds(courseIds);
	}

	@Override
	public List<MeetCourse> getMeetCourseByCourseId(Long courseId) {
		return meetCourseMapper.getMeetCourseList(courseId);
	}

	@Override
	public MeetCourse insert(MeetCourse meetCourse) {
		Assert.notNull(meetCourse, "meetCourse must not be null");
		Assert.notNull(meetCourse.getCourseId(), "meetCourse.getCourseId() must not be null");
		meetCourseMapper.insert(meetCourse);
		if(meetCourse.getMeetCourseId() == null){
			logger.error("见面课保存后返回id为null,课程id为：", meetCourse.getCourseId());
		}
		// 存缓存
		meetCourse = this.setRedisMeetCourseData(meetCourse);

		// 刷新
		this.setRedisMeetCourseIds(meetCourse.getCourseId(), meetCourse.getMeetCourseId());
		return meetCourse;
	}

	@Override
	public void delete(Long meetCourseId) {
		Assert.notNull(meetCourseId, "meetCourseId must not be null");
		meetCourseMapper.remove(meetCourseId);
		// 删除缓存
		this.removeCache(meetCourseId);
	}

}
